home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 6 code / TCP / NewsWatcher / NW Source / Source / send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-07  |  19.3 KB  |  796 lines  |  [TEXT/MMCC]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     send.c
  4.  
  5.     This module handles sending postings and mail messages.
  6.     
  7.     Copyright © 1994-1995, Northwestern University.
  8.  
  9. ----------------------------------------------------------------------------*/
  10.  
  11. #include <string.h>
  12.  
  13. #include "glob.h"
  14. #include "dialog.h"
  15. #include "news.h"
  16. #include "send.h"
  17. #include "smtp.h"
  18. #include "header.h"
  19. #include "newswatcher.h"
  20. #include "status.h"
  21. #include "message.h"
  22. #include "charset.h"
  23. #include "cancel.h"
  24. #include "memutil.h"
  25. #include "strutil.h"
  26. #include "ic.h"
  27.  
  28.  
  29.  
  30. #define kPostAlert            135            /* Post confirm dialog */
  31. #define kPostCancelAlert    147            /* Post cancel dialog */
  32.  
  33.  
  34.  
  35. /*----------------------------------------------------------------------------
  36.     Wrap 
  37.     
  38.     Wraps paragraphs to lines of at most 74 characters long.
  39.             
  40.     Entry:    text = handle to text to be wrapped.
  41.             start = offset in text of beginning of text to be wrapped.
  42.             end = offset in text of end of text to be wrapped.
  43.  
  44.      Only lines which which exceed 80 characters in length are wrapped.
  45. ----------------------------------------------------------------------------*/
  46.  
  47. void Wrap (Handle text, long start, long end)
  48. {
  49.     char *p, *pEnd, *q, *lastSpace;
  50.     
  51.     p = *text + start;
  52.     pEnd = *text + end;
  53.     while (p < pEnd) {
  54.         q = p;
  55.         while (q < pEnd && *q != CR) q++;
  56.         if (q - p > 80) {
  57.             q = p;
  58.             lastSpace = 0;
  59.             while (true) {
  60.                 while (q < pEnd && *q != ' ' && *q != CR) q++;
  61.                 if (q < pEnd && *q == ' ') {
  62.                     while (q < pEnd && *q == ' ') q++;
  63.                     q--;
  64.                 }
  65.                 if (q - p >= 75 && lastSpace != 0) {
  66.                     *lastSpace = CR;
  67.                     p = lastSpace + 1;
  68.                     lastSpace = 0;
  69.                 }
  70.                 if (q >= pEnd || *q == CR) break;
  71.                 lastSpace = q;
  72.                 q++;
  73.             }
  74.         }
  75.         p = q+1;
  76.     }
  77. }
  78.  
  79.  
  80.  
  81. /*----------------------------------------------------------------------------
  82.     UnWrap 
  83.     
  84.     Unwraps paragraphs.
  85.             
  86.     Entry:    text = handle to text to be unwrapped.
  87.             start = offset in text of beginning of text to be unwrapped.
  88.             end = offset in text of end of text to be unwrapped.
  89. ----------------------------------------------------------------------------*/
  90.  
  91. void UnWrap (Handle text, long start, long end)
  92. {
  93.     char *p, *pEnd;
  94.     
  95.     p = *text + start;
  96.     pEnd = *text + end;
  97.     while (p < pEnd) {
  98.         while (p < pEnd && *p != CR) p++;
  99.         p++;
  100.         if (p < pEnd) {
  101.             if (*p == ' ' || *p == '\t') continue;
  102.             if (*p == CR) {
  103.                 while (p < pEnd && *p == CR) p++;
  104.                 continue;
  105.             }
  106.             *(p-1) = ' ';
  107.         }
  108.     }
  109. }
  110.  
  111.  
  112.  
  113. /*----------------------------------------------------------------------------
  114.     GetRecipients 
  115.     
  116.     Gets recipient addresses for an email message.
  117.             
  118.     Entry:    text = message to be mailed, including headers.
  119.             hdr = C-format message header to process (To, Cc, or Bcc).
  120.             
  121.     Exit:    function result = error code.
  122.             *recipients = handle to comma-separated list of
  123.                 recipient email addresses, or nil if header not found.
  124. ----------------------------------------------------------------------------*/
  125.  
  126. static OSErr GetRecipients (Handle text, char *hdr, Handle *recipients)
  127. {
  128.     Handle recip;
  129.     OSErr err = noErr;
  130.     char *p, *pEnd, *q, *r, *begin, *end;
  131.     long len;
  132.     short parenLevel;
  133.     Boolean insideQuotedString = false;
  134.     
  135.     err = FindHeaderHandle(text, hdr, &recip);
  136.     if (err != noErr) return err;
  137.     if (recip == nil) {
  138.         *recipients = nil;
  139.         return noErr;
  140.     }
  141.     
  142.     /* Strip comments in parentheses and blanks. */
  143.     
  144.     p = q = *recip;
  145.     len = MyGetHandleSize(recip);
  146.     pEnd = p + len;
  147.     while (p < pEnd) {
  148.         if (*p == '(') {
  149.             parenLevel = 1;
  150.             p++;
  151.             while (p < pEnd && parenLevel > 0) {
  152.                 if (*p == '(') {
  153.                     parenLevel++;
  154.                 } else if (*p == ')') {
  155.                     parenLevel--;
  156.                 }
  157.                 p++;
  158.             }
  159.         } else if (*p == ' ') {
  160.             p++;
  161.         } else {
  162.             *q++ = *p++;
  163.         }
  164.     }
  165.     len = q - *recip;
  166.     
  167.     /* Extract recipients */
  168.     
  169.     p = q = *recip;
  170.     pEnd = p + len;
  171.     while (p < pEnd) {
  172.         r = p;
  173.         while (r < pEnd) {
  174.             if (*r == '"') {
  175.                 insideQuotedString = true;
  176.                 r++;
  177.                 while (r < pEnd && *r != '"') r++;
  178.                 if (r >= pEnd) break;
  179.                 insideQuotedString = false;
  180.                 r++;
  181.             } else if (*r == '<' || *r == ',') {
  182.                 break;
  183.             } else {
  184.                 r++;
  185.             }
  186.         }
  187.         if (insideQuotedString) break;
  188.         if (r >= pEnd || *r == ',') {
  189.             begin = p;
  190.             end = r-1;
  191.         } else {
  192.             r++;
  193.             begin = r;
  194.             while (r < pEnd && *r != '>') r++;
  195.             end = r-1;
  196.         } 
  197.         p = r;
  198.         while (p < pEnd && *p != ',') p++;
  199.         if (*p == ',') p++;
  200.         len = end - begin + 1;
  201.         if (q != *recip) *q++ = ',';
  202.         BlockMoveData(begin, q, len);
  203.         q += len;
  204.     }
  205.     len = q - *recip;
  206.     MySetHandleSize(recip, len);
  207.     *recipients = recip;
  208.     return noErr;
  209. }
  210.  
  211.  
  212.  
  213. /*----------------------------------------------------------------------------
  214.     SendMailMessage 
  215.     
  216.     Send a mail message.
  217.             
  218.     Entry:    text = message to be mailed, including headers.
  219.             
  220.     Exit:    function result = error code.
  221. ----------------------------------------------------------------------------*/
  222.  
  223. static OSErr SendMailMessage (Handle text)
  224. {
  225.     SmtpStreamRef s;
  226.     OSErr err = noErr;
  227.     Handle to = nil;
  228.     Handle cc = nil;
  229.     Handle bcc = nil;
  230.     long toLen, ccLen, bccLen, len;
  231.     char *q;
  232.     NetServerErrInfo serverErrInfo;
  233.     
  234.     MyICReadSharedPrefs(kICEmail);
  235.     MyICReadSharedPrefs(kICSMTPHost);
  236.     
  237.     err = GetRecipients(text, "To", &to);
  238.     if (err != noErr) goto exit1;
  239.     err = GetRecipients(text, "Cc", &cc);
  240.     if (err != noErr) goto exit1;
  241.     err = GetRecipients(text, "Bcc", &bcc);
  242.     if (err != noErr) goto exit1;
  243.     
  244.     toLen = to == nil ? 0 : MyGetHandleSize(to);
  245.     ccLen = cc == nil ? 0 : MyGetHandleSize(cc);
  246.     bccLen = bcc == nil ? 0 : MyGetHandleSize(bcc);
  247.     
  248.     len = toLen;
  249.     if (cc != nil) {
  250.         if (len > 0) len++;
  251.         len += ccLen;
  252.     }
  253.     if (bcc != nil) {
  254.         if (len > 0) len++;
  255.         len += bccLen;
  256.     }
  257.     len++;
  258.     
  259.     if (to == nil) {
  260.         err = MyNewHandle(len, &to);
  261.     } else {
  262.         err = MySetHandleSize(to, len);
  263.     }
  264.     if (err != noErr) goto exit1;
  265.     
  266.     q = *to + toLen;
  267.     if (cc != nil) {
  268.         if (q > *to) *q++ = ',';
  269.         BlockMoveData(*cc, q, ccLen);
  270.         q += ccLen;
  271.     }
  272.     if (bcc != nil) {
  273.         if (q > *to) *q++ = ',';
  274.         BlockMoveData(*bcc, q, bccLen);
  275.         q += bccLen;
  276.     }
  277.     *q = 0;
  278.     
  279.     p2cstr(gPrefs.mailServerName);
  280.     err = SmtpOpen((char*)gPrefs.mailServerName, &s);
  281.     c2pstr((char*)gPrefs.mailServerName);
  282.     if (err != noErr) goto exit2;
  283.     
  284.     MyHLock(to);
  285.     err = SmtpSendMessage(s, gPrefs.emailAddress, *to, text);
  286.     MyHUnlock(to);
  287.     if (err != noErr) goto exit2;
  288.     
  289.     err = SmtpClose(s);
  290.     if (err != noErr) goto exit2;
  291.     
  292.     MyDisposeHandle(to);
  293.     MyDisposeHandle(cc);
  294.     MyDisposeHandle(bcc);
  295.     
  296.     return noErr;
  297.     
  298. exit1:
  299.     
  300.     MyDisposeHandle(to);
  301.     MyDisposeHandle(cc);
  302.     MyDisposeHandle(bcc);
  303.     return err;
  304.     
  305. exit2:
  306.     
  307.     MyDisposeHandle(to);
  308.     MyDisposeHandle(cc);
  309.     MyDisposeHandle(bcc);
  310.     if (err == smtpServerErr) {
  311.         SmtpGetServerErrInfo(s, &serverErrInfo);
  312.         SmtpClose(s);
  313.         ServerErrorMessage(kStrMail, serverErrInfo.command, serverErrInfo.response);
  314.         return userCanceledErr;
  315.     } else {
  316.         p2cstr(gPrefs.mailServerName);
  317.         SaveNetErrorInfo(kStrMail, (char*)gPrefs.mailServerName);
  318.         c2pstr((char*)gPrefs.mailServerName);
  319.         return err;
  320.     }
  321. }
  322.  
  323.  
  324.  
  325. /*----------------------------------------------------------------------------
  326.     AreYouSure 
  327.     
  328.     Present "Are you sure you want to post" alert.
  329.             
  330.     Exit:    function result = error code.
  331. ----------------------------------------------------------------------------*/
  332.  
  333. static OSErr AreYouSure (void)
  334. {
  335.     DialogPtr dlg = nil;
  336.     short item;
  337.     OSErr err = noErr;
  338.  
  339.     if (!gPrefs.areYouSureAlert) return noErr;
  340.     err = MyGetNewDialog(kPostAlert, ok, cancel, &dlg);
  341.     if (err != noErr) return err;
  342.     SysBeep(0);
  343.     MyModalDialog(dlg, gDialogFilterUPP, &item);
  344.     err = DoClose(dlg);
  345.     if (err != noErr) return err;
  346.     return item == ok ? noErr : userCanceledErr;
  347. }
  348.  
  349.  
  350.  
  351. /*----------------------------------------------------------------------------
  352.     BuildMessageForPrinting 
  353.     
  354.     Build a message for printing.
  355.             
  356.     Entry:    wind = pointer to message window.
  357.             
  358.     Exit:    function result = error code.
  359.             *messageText = handle to message text to be printed.
  360. ----------------------------------------------------------------------------*/
  361.  
  362. OSErr BuildMessageForPrinting (WindowPtr wind, Handle *messageText)
  363. {
  364.     TWindow **info;
  365.     TEHandle theTE;
  366.     Handle text = nil;
  367.     Handle msg = nil;
  368.     Handle newsgroups, to, subject, cc, bcc, replyto;
  369.     Handle followupto, keywords, distribution;
  370.     Handle extraMail, signature, references;
  371.     OSErr err = noErr, err1 = noErr;
  372.     long sigLen, textLen, newTextLen;
  373.     char *q;
  374.     Boolean newsIcon, mailIcon, selfIcon;
  375.  
  376.     info = (TWindow**)GetWRefCon(wind);
  377.     theTE = (**info).theTE;
  378.     text = (**theTE).hText;
  379.     newsgroups = (**(**info).newsgroupsField).hText;
  380.     to = (**(**info).toField).hText;
  381.     subject = (**(**info).subjectField).hText;
  382.     cc = (**(**info).ccField).hText;
  383.     bcc = (**(**info).bccField).hText;
  384.     replyto = (**(**info).replytoField).hText;
  385.     followupto = (**(**info).followuptoField).hText;
  386.     keywords = (**(**info).keywordsField).hText;
  387.     distribution = (**(**info).distributionField).hText;
  388.     extraMail = (**(**info).extraMailField).hText;
  389.     signature = (**(**info).signatureField).hText;
  390.     references = (**info).references;
  391.     newsIcon = (**info).newsIcon;
  392.     mailIcon = (**info).mailIcon;
  393.     selfIcon = (**info).selfIcon;
  394.     
  395.     err = MyHandToHand(&text);
  396.     if (err != noErr) return err;
  397.     
  398.     textLen = MyGetHandleSize(text);
  399.     q = *text + textLen - 1;
  400.     while (q > *text && isLWSPorCR(*q)) q--;
  401.     q++;
  402.     newTextLen = q - *text;
  403.     if (newTextLen != textLen) {
  404.         textLen = newTextLen;
  405.         MySetHandleSize(text, textLen);
  406.     }
  407.  
  408.     sigLen = MyGetHandleSize(signature);
  409.     if (sigLen > 0) {
  410.         newTextLen = textLen + sigLen + 1;
  411.         err = MySetHandleSize(text, newTextLen);
  412.         if (err != noErr) goto exit;
  413.         q = *text + textLen;
  414.         *q++ = CR;
  415.         BlockMoveData(*signature, q, sigLen);
  416.         textLen = newTextLen;
  417.     }
  418.     
  419.     if (textLen == 0) {
  420.         textLen = 1;
  421.         err = MySetHandleSize(text, textLen);
  422.         if (err != noErr) goto exit;
  423.         **text = ' ';
  424.     }
  425.     
  426.     if (!mailIcon) to = cc = bcc = nil;
  427.     if (!newsIcon) newsgroups = followupto = distribution = nil;
  428.     err = MakeMailHeader(subject, to, cc, bcc, (**info).from,
  429.         (**info).selfIcon, replyto, keywords, extraMail,
  430.         newsgroups, followupto, distribution,
  431.         references, &msg);
  432.     if (err != noErr) goto exit;
  433.     err = MyHandAndHand(text, msg);
  434.     if (err != noErr) goto exit;
  435.     
  436.     *messageText = msg;
  437.     MyDisposeHandle(text);
  438.     return noErr;
  439.     
  440. exit:
  441.  
  442.     MyDisposeHandle(text);
  443.     MyDisposeHandle(msg);
  444.     return err;
  445. }
  446.  
  447.  
  448.  
  449. /*----------------------------------------------------------------------------
  450.     MessageBodyContainsOnlyQuotedText 
  451.     
  452.     Check to see if a message body contains only quoted text.
  453.             
  454.     Entry:    text = handle to message body text.
  455.             quoteString = handle to quote string.
  456.             
  457.     Exit:    function result = true if message body contains only quoted text
  458.                 and blank lines (not counting the beginning attribution line).
  459. ----------------------------------------------------------------------------*/
  460.  
  461. static Boolean MessageBodyContainsOnlyQuotedText (Handle text, Handle quoteString)
  462. {
  463.     long textLen, quoteStringLen;
  464.     char *p, *pEnd, *r;
  465.     CStr255 attributionStr1, attributionStr3;
  466.     short attributionStr1Len, attributionStr3Len;
  467.     
  468.     textLen = MyGetHandleSize(text);
  469.     quoteStringLen = MyGetHandleSize(quoteString);
  470.     if (quoteStringLen == 0) return false;
  471.     
  472.     GetCString(kStrQuoteStr1, attributionStr1);
  473.     GetCString(kStrQuoteStr3, attributionStr3);
  474.     attributionStr1Len = strlen(attributionStr1);
  475.     attributionStr3Len = strlen(attributionStr3);
  476.  
  477.     p = *text;
  478.     pEnd = p + textLen;
  479.     
  480.     /* Check the first line of the message body. If it is the attribution line
  481.        "In article <...>, so-and-so wrote:", then skip over it. */
  482.     
  483.     r = p;
  484.     while (r < pEnd && *r != CR) r++;
  485.     if (r - p > attributionStr1Len + attributionStr3Len + 10) {
  486.         if (MyStrNEqual(p, attributionStr1, attributionStr1Len) &&
  487.             *(p + attributionStr1Len) == '<' &&
  488.             MyStrNEqual(r - attributionStr3Len, attributionStr3, attributionStr3Len))
  489.         {
  490.             p = r+1;
  491.         }
  492.     }
  493.     
  494.     /* Check the remaining lines of the message body for only quoted and blank
  495.        lines. */
  496.     
  497.     while (p < pEnd) {
  498.         r = p;
  499.         while (r < pEnd && isLWSP(*r)) r++;
  500.         if (r >= pEnd) return true;
  501.         if (*r == CR) {        /* all blank line */
  502.             p = r+1;
  503.             continue;
  504.         }
  505.         if (p + quoteStringLen > pEnd) return false;
  506.         if (!MyStrNEqual(p, *quoteString, quoteStringLen)) return false;
  507.         p = r+1;
  508.         while (p < pEnd && *p != CR) p++;
  509.         p++;
  510.     }
  511.     
  512.     return true;
  513. }
  514.             
  515.  
  516.  
  517.  
  518. /*----------------------------------------------------------------------------
  519.     MakeAlsoPostedToText 
  520.     
  521.     Construct the "(A copy of this message was also posted to...)" text for
  522.     a mail message which is also being posted.
  523.             
  524.     Entry:    headers = handle to header text for mail message.
  525.             
  526.     Exit:    function result = error code.
  527.             *alsoPostedTo = handle to extra "also posted to" text to
  528.                 be added to beginning of mail message.
  529. ----------------------------------------------------------------------------*/
  530.  
  531. static OSErr MakeAlsoPostedToText (Handle headers, Handle *alsoPostedTo)
  532. {            
  533.     CStr255 str;
  534.     OSErr err = noErr;
  535.     Handle h = nil;
  536.     Handle newsgroups = nil;
  537.  
  538.     GetCString(kStrCopyAlsoPostedTo, str);
  539.     err = MyPtrToHand(str, &h, strlen(str));
  540.     if (err != noErr) goto exit;
  541.     err = FindHeaderHandle(headers, "Newsgroups", &newsgroups);
  542.     if (err != noErr) goto exit;
  543.     if (newsgroups != nil) {
  544.         Munger(newsgroups, 0, ",", 1, ", ", 2);
  545.         err = MemError();
  546.         if (err != noErr) goto exit;
  547.         err = MyHandAndHand(newsgroups, h);
  548.         if (err != noErr) goto exit;
  549.     }
  550.     err = MyStrAndHand(")\r\r", h);
  551.     if (err != noErr) goto exit;
  552.     Wrap(h, 0, MyGetHandleSize(h));
  553.     MyDisposeHandle(newsgroups);
  554.     *alsoPostedTo = h;
  555.     return noErr;
  556.     
  557. exit:
  558.  
  559.     MyDisposeHandle(h);
  560.     MyDisposeHandle(newsgroups);
  561.     return err;
  562. }
  563.             
  564.  
  565.  
  566.  
  567. /*----------------------------------------------------------------------------
  568.     SendMessage 
  569.     
  570.     Send a message.
  571.             
  572.     Entry:    wind = pointer to message window.
  573.             
  574.     Exit:    function result = error code.
  575. ----------------------------------------------------------------------------*/
  576.  
  577. OSErr SendMessage (WindowPtr wind)
  578. {
  579.     TWindow **info;
  580.     TEHandle theTE;
  581.     Handle text = nil;
  582.     Handle msg = nil;
  583.     Handle newsgroups, to, subject, cc, bcc, replyto;
  584.     Handle followupto, keywords, distribution;
  585.     Handle extraNews, extraMail, signature, references;
  586.     Handle alsoPostedTo = nil;
  587.     OSErr err = noErr, err1 = noErr;
  588.     long sigLen, textLen, newTextLen;
  589.     char *q;
  590.     Boolean newsIcon, mailIcon, selfIcon;
  591.     short item;
  592.     CStr255 idStr;
  593.     CStr255 statusMsg;
  594.     FSSpec fSpec;
  595.     Boolean wasChanged;
  596.     Boolean posted = false, postIndeterminate = false, mailStarted = false;
  597.     DialogPtr dlg = nil;
  598.  
  599.     info = (TWindow**)GetWRefCon(wind);
  600.     theTE = (**info).theTE;
  601.     text = (**theTE).hText;
  602.     newsgroups = (**(**info).newsgroupsField).hText;
  603.     to = (**(**info).toField).hText;
  604.     subject = (**(**info).subjectField).hText;
  605.     cc = (**(**info).ccField).hText;
  606.     bcc = (**(**info).bccField).hText;
  607.     replyto = (**(**info).replytoField).hText;
  608.     followupto = (**(**info).followuptoField).hText;
  609.     keywords = (**(**info).keywordsField).hText;
  610.     distribution = (**(**info).distributionField).hText;
  611.     extraNews = (**(**info).extraNewsField).hText;
  612.     extraMail = (**(**info).extraMailField).hText;
  613.     signature = (**(**info).signatureField).hText;
  614.     references = (**info).references;
  615.     newsIcon = (**info).newsIcon;
  616.     mailIcon = (**info).mailIcon;
  617.     selfIcon = (**info).selfIcon;
  618.     
  619.     if (!newsIcon && !mailIcon && !selfIcon) {
  620.         ErrorMessageNumber(kStrMustCheckAnIcon);
  621.         return userCanceledErr;
  622.     }
  623.     
  624.     if (HeaderLineIsEmpty(subject)) {
  625.         ErrorMessageNumber(kStrMustSupplySubject);
  626.         return userCanceledErr;
  627.     }
  628.     
  629.     if (newsIcon && HeaderLineIsEmpty(newsgroups)) {
  630.         ErrorMessageNumber(kStrMustSupplyNewsgroup);
  631.         return userCanceledErr;
  632.     }
  633.     
  634.     if (mailIcon && !selfIcon && 
  635.         HeaderLineIsEmpty(to) && HeaderLineIsEmpty(cc) && HeaderLineIsEmpty(bcc)) 
  636.     {
  637.         ErrorMessageNumber(kStrMustSupplyRecipient);
  638.         return userCanceledErr;
  639.     }
  640.     
  641.     err = MyHandToHand(&text);
  642.     if (err != noErr) return err;
  643.     
  644.     textLen = MyGetHandleSize(text);
  645.     q = *text + textLen - 1;
  646.     while (q > *text && isLWSPorCR(*q)) q--;
  647.     q++;
  648.     newTextLen = q - *text;
  649.     if (newTextLen != textLen) {
  650.         textLen = newTextLen;
  651.         MySetHandleSize(text, textLen);
  652.     }
  653.     
  654.     if (textLen == 0) {
  655.         ErrorMessageNumber(kStrMustSupplyBody);
  656.         err = userCanceledErr;
  657.         goto exit;
  658.     }
  659.     
  660.     if (newsIcon && (**info).isFollowup && 
  661.         MessageBodyContainsOnlyQuotedText(text, (**(**info).quoteStringField).hText)) 
  662.     {
  663.         ErrorMessageNumber(kStrOnlyQuotedText);
  664.         err = userCanceledErr;
  665.         goto exit;
  666.     }
  667.     
  668.     if (newsIcon) {
  669.         err = AreYouSure();
  670.         if (err != noErr) goto exit;
  671.     }
  672.     
  673.     if ((**info).wrapOnSend) Wrap(text, 0, textLen);
  674.  
  675.     sigLen = MyGetHandleSize(signature);
  676.     if (sigLen > 0) {
  677.         newTextLen = textLen + sigLen + 1;
  678.         err = MySetHandleSize(text, newTextLen);
  679.         if (err != noErr) goto exit;
  680.         q = *text + textLen;
  681.         *q++ = CR;
  682.         BlockMoveData(*signature, q, sigLen);
  683.         textLen = newTextLen;
  684.     }
  685.     
  686.     if (newsIcon) {
  687.         GetCString(kStrPostingMessageStatusMsg, statusMsg);
  688.         err = DisplayStatusMessage(statusMsg);
  689.         if (err != noErr) goto exit;
  690.         err = MakeNewsHeader(newsgroups, subject, replyto, 
  691.             followupto, keywords, distribution, extraNews,
  692.             nil, references, &msg);
  693.         if (err != noErr) goto exit;
  694.         FindHeaderCString(msg, "Message-ID", idStr, sizeof(idStr));
  695.         err = MyHandAndHand(text, msg);
  696.         if (err != noErr) goto exit;
  697.         MapMacToLatin1Handle(msg);
  698.         err = PostArticle(msg, statusMsg, &postIndeterminate);
  699.         posted = err == noErr || postIndeterminate;
  700.         if (err != noErr) goto exit;
  701.         MyDisposeHandle(msg);
  702.         msg = nil;
  703.     }
  704.     
  705.     if (mailIcon || selfIcon) {
  706.         mailStarted = true;
  707.         err = DisplayStatusMessageNumber(kStrMailingMessageStatusMsg);
  708.         if (err != noErr) goto exit;
  709.         if (!mailIcon) to = cc = bcc = nil;
  710.         if (!newsIcon) newsgroups = followupto = distribution = nil;
  711.         err = MakeMailHeader(subject, to, cc, bcc, (**info).from,
  712.             (**info).selfIcon, replyto, keywords, extraMail,
  713.             newsgroups, followupto, distribution,
  714.             references, &msg);
  715.         if (err != noErr) goto exit;
  716.         if (mailIcon && newsIcon) {
  717.             err = MakeAlsoPostedToText(msg, &alsoPostedTo);
  718.             if (err != noErr) goto exit;
  719.             err = MyHandAndHand(alsoPostedTo, msg);
  720.             if (err != noErr) goto exit;
  721.             MyDisposeHandle(alsoPostedTo);
  722.             alsoPostedTo = nil;
  723.         }
  724.         err = MyHandAndHand(text, msg);
  725.         if (err != noErr) goto exit;
  726.         MapMacToLatin1Handle(msg);
  727.         err = SendMailMessage(msg);
  728.         if (err != noErr) goto exit;
  729.     }
  730.  
  731.     (**info).changed = false;
  732.     MyDisposeHandle(text);
  733.     MyDisposeHandle(msg);
  734.     
  735.     if ((**info).alias != nil && gPrefs.savedMsgDelAfterSend) {
  736.         err = ResolveAlias(nil, (**info).alias, &fSpec, &wasChanged);
  737.         if (err == noErr) {
  738.             (**info).alias = nil;
  739.             err = FSpDelete(&fSpec);
  740.             if (err != noErr) return err;
  741.         }
  742.     }
  743.     
  744.     return noErr;
  745.     
  746. exit:
  747.  
  748.     MyDisposeHandle(text);
  749.     MyDisposeHandle(msg);
  750.     MyDisposeHandle(alsoPostedTo);
  751.     if (gCancel && posted) {
  752.         gCancel = false;
  753.         UncheckNewsIcon(wind);
  754.         err1 = MyGetNewDialog(kPostCancelAlert, ok, cancel, &dlg);
  755.         if (err1 != noErr) return err1;
  756.         SysBeep(0);
  757.         MyModalDialog(dlg, gDialogFilterUPP, &item);
  758.         err1 = DoClose(dlg);
  759.         if (err1 != noErr) return err1;
  760.         if (item == cancel) {
  761.             GetCString(kStrCancelingStatusMsg, statusMsg);
  762.             err1 = DisplayStatusMessage(statusMsg);
  763.             if (err1 != noErr) return err1;
  764.             err1 = CancelArticle(idStr, newsgroups, statusMsg);
  765.             if (err1 != noErr) return err1;
  766.         }
  767.     } else if (posted && mailStarted) {
  768.         UncheckNewsIcon(wind);
  769.         ReportSystemError(err);
  770.         NoteMessageNumber(kStrPostOKMailErr);
  771.         return userCanceledErr;
  772.     }
  773.     return err;
  774. }
  775.  
  776.  
  777.  
  778. /*----------------------------------------------------------------------------
  779.     SendMessageAndCloseWindow 
  780.     
  781.     Send a message and close the message window.
  782.             
  783.     Entry:    wind = pointer to message window.
  784.     
  785.     Exit:    function result = error code.
  786. ----------------------------------------------------------------------------*/
  787.  
  788. OSErr SendMessageAndCloseWindow (WindowPtr wind)
  789. {
  790.     OSErr err = noErr;
  791.  
  792.     err = SendMessage(wind);
  793.     if (err != noErr) return err;
  794.     return DoClose(wind);
  795. }
  796.